package com.iot.auth.service.impl;


import com.dc3.common.bean.R;
import com.dc3.common.constant.CacheConstant;
import com.dc3.common.utils.Dc3Util;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.iot.auth.service.TokenService;
import com.iot.openfeign.CacheClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.util.Map;

/**
 * @Author 咕唧
 * @Date 2022/7/19 21:20
 * @Version 1.0
 */
@Component
@Transactional
public class TokenServiceImpl implements TokenService {
    private CacheClient cacheClient;

    private ObjectMapper objectMapper;

    @Autowired
    public void setObjectMapper(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Resource
    public void setCacheClient(CacheClient cacheClient) {
        this.cacheClient = cacheClient;
    }

    @Override
    public Mono<Integer> checkToken(String token) {
        //获取传递的令牌 和 redis 缓存中进行对比 key就是令牌中保存的数据
//        return Mono.just(token)
//                .map(jwt -> jwt.split("\\."))
//                .flatMap(strings -> {
//                    try {
//                        //转换数据
//                        Map map = objectMapper.readValue(Dc3Util.decode(strings[1]), Map.class);
//                        //获取请求头中令牌的数据
//                        String username = (String) map.get("sub");
//                        String tenantName = (String) map.get("tenantName");
//
//                        //根据转换的数据查询redis缓存，如果存在;则没有问题，成功登录
//                        String key = CacheConstant.Entity.TENANT + tenantName + CacheConstant.Entity.USER + username + CacheConstant.Suffix.SALT;
//                        return cacheClient.getValue(key).map(R::getData);//获取到盐
//                        //TODO 如果redis中保存的时候jwt地方数据,在这里获取到就是jwt数据
//                    } catch (Exception e) {
//                        return Mono.error(new RuntimeException("令牌错误"));
//                    }
//                })
//                .flatMap(salt -> {
//                    try {
//                        //只要不对,就会出现异常,如果没有问题就不会有异常
//                        Jwt jwt = Jwts.parser().setSigningKey(salt.toString().getBytes(StandardCharsets.UTF_8)).parse(token);
//                        return Mono.just(1);//如果没有问题就返回1
//                    } catch (Exception e) {
//                        return Mono.error(new RuntimeException("令牌过期了"));
//                    }
//                    //TODO 如果上面获取到的是jwt的内容,在这里应该进行比较,看看内容是否一致, 一致就代表尚未过期,可以放行,不一致就代表不对·
//                })
//                .onErrorReturn(throwable -> {
//                    System.err.println(throwable.getMessage());
//                    //返回true就是用当前的返回值,返回false就是不处理这个异常,我们可以在这里根据业务决定返回什么值
//                    return true;
//                }, 0)
//                .defaultIfEmpty(0);
        return Mono.just(token)
                .map(jwt -> jwt.split("\\."))
                .flatMap(strings -> {
                    try {
                        //转换数据
                        Map map = objectMapper.readValue(Dc3Util.decode(strings[1]), Map.class);
                        //获取请求头中令牌的数据
                        String username = (String) map.get("sub");
                        String tenantName = (String) map.get("tenantName");
                        String key = CacheConstant.Entity.TENANT + tenantName + CacheConstant.Entity.USER + username + CacheConstant.Suffix.SALT;
                        //根据转换的数据查询redis缓存，如果存在;则没有问题，成功登录

                        return cacheClient.getValue(key).map(R::getData)
                                .filter(tok -> tok.equals(token))
                                .map(s-> 1)
                                .defaultIfEmpty(0);
                    } catch (Exception e) {
                        return Mono.error(new RuntimeException("令牌错误"));
                    }
                })
                .onErrorReturn(throwable -> {
                    System.err.println(throwable.getMessage());
                    //返回true就是用当前的返回值,返回false就是不处理这个异常,我们可以在这里根据业务决定返回什么值
                    return true;
                }, 0);
    }
}
